import mysql.connector
from mysql.connector import Error
import bcrypt
import re


class UserAuth:
    def __init__(self, host, database, user, password):
        """初始化数据库连接参数"""
        self.host = host
        self.database = database
        self.user = user
        self.password = password
        self.connection = None
        self.cursor = None

    def connect(self):
        """建立数据库连接"""
        try:
            self.connection = mysql.connector.connect(
                host=self.host,
                database=self.database,
                user=self.user,
                password=self.password
            )
            if self.connection.is_connected():
                self.cursor = self.connection.cursor(dictionary=True)
                return True
        except Error as e:
            print(f"数据库连接错误: {e}")
        return False

    def disconnect(self):
        """关闭数据库连接"""
        if self.connection and self.connection.is_connected():
            self.cursor.close()
            self.connection.close()

    def create_table(self):
        """创建用户表（如果不存在）"""
        if not self.connection or not self.connection.is_connected():
            if not self.connect():
                return False

        try:
            create_table_query = """
                                 CREATE TABLE IF NOT EXISTS users \
                                 ( \
                                     id \
                                     INT \
                                     AUTO_INCREMENT \
                                     PRIMARY \
                                     KEY, \
                                     username \
                                     VARCHAR \
                                 ( \
                                     50 \
                                 ) NOT NULL UNIQUE,
                                     email VARCHAR \
                                 ( \
                                     100 \
                                 ) NOT NULL UNIQUE,
                                     password_hash VARCHAR \
                                 ( \
                                     255 \
                                 ) NOT NULL,
                                     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                                     ) \
                                 """
            self.cursor.execute(create_table_query)
            self.connection.commit()
            return True
        except Error as e:
            print(f"创建表错误: {e}")
            return False

    def validate_email(self, email):
        """验证邮箱格式"""
        pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
        return re.match(pattern, email) is not None

    def validate_password(self, password):
        """验证密码强度（至少8位，包含字母和数字）"""
        if len(password) < 8:
            return False
        if not re.search(r'[A-Za-z]', password):
            return False
        if not re.search(r'[0-9]', password):
            return False
        return True

    def register(self, username, email, password):
        """注册新用户"""
        if not self.connection or not self.connection.is_connected():
            if not self.connect():
                return False, "无法连接到数据库"

        # 验证输入
        if not username or not email or not password:
            return False, "所有字段都是必填的"

        if not self.validate_email(email):
            return False, "无效的邮箱格式"

        if not self.validate_password(password):
            return False, "密码必须至少8位，包含字母和数字"

        try:
            # 检查用户名是否已存在
            self.cursor.execute("SELECT id FROM users WHERE username = %s", (username,))
            if self.cursor.fetchone():
                return False, "用户名已存在"

            # 检查邮箱是否已存在
            self.cursor.execute("SELECT id FROM users WHERE email = %s", (email,))
            if self.cursor.fetchone():
                return False, "邮箱已被注册"

            # 密码哈希处理
            password_hash = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())

            # 插入新用户
            insert_query = """
                           INSERT INTO users (username, email, password_hash)
                           VALUES (%s, %s, %s) \
                           """
            self.cursor.execute(insert_query, (username, email, password_hash.decode('utf-8')))
            self.connection.commit()

            return True, "注册成功"

        except Error as e:
            self.connection.rollback()
            return False, f"注册失败: {str(e)}"

    def login(self, username, password):
        """用户登录验证"""
        if not self.connection or not self.connection.is_connected():
            if not self.connect():
                return False, "无法连接到数据库"

        try:
            # 查询用户
            self.cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
            user = self.cursor.fetchone()

            if not user:
                return False, "用户名不存在"

            # 验证密码
            if bcrypt.checkpw(password.encode('utf-8'), user['password_hash'].encode('utf-8')):
                return True, "登录成功", user
            else:
                return False, "密码错误"

        except Error as e:
            return False, f"登录失败: {str(e)}"


# 使用示例
if __name__ == "__main__":
    # 数据库连接参数，请根据实际情况修改
    db_config = {
        'host': 'localhost',
        'database': 'user_auth_db',
        'user': 'root',
        'password': 'ht2025'  # 替换为你的数据库密码
    }

    # 创建用户认证实例
    auth = UserAuth(**db_config)

    # 连接数据库并创建表
    if auth.connect():
        auth.create_table()

        # 示例：注册新用户
        reg_success, reg_msg = auth.register(
            username="admin",
            email="test@example.com",
            password="admin"  # 符合密码要求
        )
        print(f"注册: {reg_msg}")

        # 示例：用户登录
        login_success, login_msg, user_data = auth.login(
            username="admin",
            password="admin"
        )
        print(f"登录: {login_msg}")

        if login_success and user_data:
            print(f"欢迎回来，{user_data['username']}！")

        # 关闭连接
        auth.disconnect()
    else:
        print("无法连接到数据库")
